/*     */ package com.zimbra.cs.zimlet;
/*     */ 
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.util.BufferStream;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Props2Js;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import java.io.ByteArrayInputStream;
/*     */ import java.io.ByteArrayOutputStream;
/*     */ import java.io.DataOutputStream;
/*     */ import java.io.File;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.OutputStream;
/*     */ import java.util.Arrays;
/*     */ import java.util.Collections;
/*     */ import java.util.HashMap;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Locale;
/*     */ import java.util.Map;
/*     */ import java.util.MissingResourceException;
/*     */ import java.util.ResourceBundle;
/*     */ import java.util.ResourceBundle.Control;
/*     */ import java.util.StringTokenizer;
/*     */ import java.util.regex.Matcher;
/*     */ import java.util.regex.Pattern;
/*     */ import java.util.zip.GZIPOutputStream;
/*     */ import javax.servlet.ServletConfig;
/*     */ import javax.servlet.ServletContext;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.ServletRequest;
/*     */ import javax.servlet.ServletResponse;
/*     */ import javax.servlet.http.HttpServlet;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ZimletProps2JsServlet
/*     */   extends HttpServlet
/*     */ {
/*     */   private static final long serialVersionUID = -312514257671213969L;
/*     */   protected static final String COMPRESSED_EXT = ".zgz";
/*     */   protected static final String P_DEBUG = "debug";
/*     */   protected static final String P_BASENAME_PATTERNS = "basename-patterns";
/*     */   protected static final String A_FLUSH_CACHE = "flushCache";
/*     */   protected static final String A_REQUEST_URI = "request-uri";
/*     */   protected static final String A_BASENAME_PATTERNS = "basename-patterns";
/*     */   protected static final String A_BASENAME_PATTERNS_LIST = "basename-patterns-list";
/*  70 */   private static Map<Locale, Map<String, byte[]>> buffers = new HashMap();
/*     */   
/*     */   private String getDirPath(String dirname)
/*     */   {
/*  74 */     if (new File(dirname).isAbsolute()) {
/*  75 */       return dirname;
/*     */     }
/*  77 */     String basedir = getServletContext().getRealPath("/");
/*  78 */     if (!basedir.endsWith("/")) {
/*  79 */       basedir = basedir + "/";
/*     */     }
/*  81 */     return basedir + dirname;
/*     */   }
/*     */   
/*     */   public void service(ServletRequest req, ServletResponse resp)
/*     */     throws IOException, ServletException
/*     */   {
/*  87 */     if (flushCache(req)) {
/*  88 */       return;
/*     */     }
/*  90 */     super.service(req, resp);
/*     */   }
/*     */   
/*     */ 
/*     */   public void doGet(HttpServletRequest req, HttpServletResponse resp)
/*     */     throws IOException, ServletException
/*     */   {
/*  97 */     boolean debug = req.getParameter("debug") != null;
/*  98 */     Locale locale = getLocale(req);
/*     */     
/* 100 */     String uri = getRequestURI(req);
/* 101 */     ZimbraLog.zimlet.debug("ZimletProps2JsServlet uri: %s", new Object[] { uri });
/* 102 */     ZimbraLog.zimlet.debug("ZimletProps2JsServlet base context path: %s", new Object[] { getServletConfig().getServletContext().getContextPath() });
/*     */     
/*     */     Map<String, byte[]> localeBuffers;
/* 105 */     synchronized (buffers) {
/* 106 */       localeBuffers = (Map)buffers.get(locale);
/* 107 */       if (localeBuffers == null) {
/* 108 */         localeBuffers = Collections.synchronizedMap(new HashMap());
/*     */         
/* 110 */         buffers.put(locale, localeBuffers);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 115 */     byte[] buffer = debug ? null : (byte[])localeBuffers.get(uri);
/*     */     
/* 117 */     if (buffer == null) {
/* 118 */       buffer = getBuffer(req, locale, uri);
/*     */       
/* 120 */       if (uri.endsWith(".zgz"))
/*     */       {
/* 122 */         ByteArrayOutputStream bos = new ByteArrayOutputStream(buffer.length / 2);
/* 123 */         OutputStream gzos = new GZIPOutputStream(bos);
/*     */         
/* 125 */         gzos.write(buffer);
/* 126 */         gzos.close();
/* 127 */         buffer = bos.toByteArray();
/*     */       }
/* 129 */       if (!LC.zimbra_minimize_resources.booleanValue()) {
/* 130 */         localeBuffers.put(uri, buffer);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 135 */     Object out = resp.getOutputStream();
/*     */     try {
/* 137 */       if (uri.endsWith(".zgz")) {
/* 138 */         resp.setHeader("Content-Encoding", "gzip");
/*     */       }
/* 140 */       resp.setContentType("application/x-javascript");
/*     */     } catch (Exception e) {
/* 142 */       ZimbraLog.zimlet.error(e.getMessage());
/*     */     }
/* 144 */     ((OutputStream)out).write(buffer);
/* 145 */     ((OutputStream)out).flush();
/*     */   }
/*     */   
/*     */   protected boolean flushCache(ServletRequest req) {
/* 149 */     Boolean flushCache = (Boolean)req.getAttribute("flushCache");
/* 150 */     if ((flushCache != null) && (flushCache.booleanValue())) {
/* 151 */       int oldSize = buffers.size();
/* 152 */       buffers.clear();
/* 153 */       int newSize = buffers.size();
/* 154 */       ZimbraLog.zimlet.debug("flushed uistrings cache: %d entries > %d entries", new Object[] { Integer.valueOf(oldSize), Integer.valueOf(newSize) });
/* 155 */       return true;
/*     */     }
/* 157 */     return false;
/*     */   }
/*     */   
/*     */   protected String getRequestURI(HttpServletRequest req) {
/* 161 */     String uri = (String)req.getAttribute("request-uri");
/* 162 */     if (uri == null) {
/* 163 */       uri = req.getRequestURI();
/*     */     }
/* 165 */     return uri;
/*     */   }
/*     */   
/*     */   protected List<String> getBasenamePatternsList(HttpServletRequest req) {
/* 169 */     List<String> list = new LinkedList();
/* 170 */     String patterns = (String)req.getAttribute("basename-patterns");
/*     */     
/* 172 */     if (patterns == null) {
/* 173 */       patterns = getInitParameter("basename-patterns");
/*     */     }
/* 175 */     if (patterns == null) {
/* 176 */       patterns = "WEB-INF/classes/${dir}/${name}";
/*     */     }
/* 178 */     list.add(patterns);
/* 179 */     return list;
/*     */   }
/*     */   
/*     */   protected Locale getLocale(HttpServletRequest req) {
/* 183 */     String language = req.getParameter("language");
/* 184 */     String locid = req.getParameter("locid");
/* 185 */     if (language != null) {
/* 186 */       String country = req.getParameter("country");
/* 187 */       if (country != null) {
/* 188 */         return new Locale(language, country);
/*     */       }
/* 190 */       return new Locale(language);
/*     */     }
/* 192 */     if (locid != null) {
/* 193 */       String[] parts = locid.split("_");
/* 194 */       if (parts.length > 1) {
/* 195 */         return new Locale(parts[0], parts[1]);
/*     */       }
/* 197 */       return new Locale(parts[0]);
/*     */     }
/*     */     
/* 200 */     return req.getLocale();
/*     */   }
/*     */   
/*     */   protected byte[] getBuffer(HttpServletRequest req, Locale locale, String uri) throws IOException
/*     */   {
/* 205 */     BufferStream bos = new BufferStream(24576L);
/* 206 */     DataOutputStream out = new DataOutputStream(bos);
/* 207 */     out.writeBytes("// Locale: " + Props2Js.getCommentSafeString(locale.toString()) + '\n');
/*     */     
/*     */ 
/* 210 */     List<String> patternsList = getBasenamePatternsList(req);
/* 211 */     List<List<String>> basenamePatterns = new LinkedList();
/* 212 */     for (String patterns : patternsList) {
/* 213 */       StringTokenizer tokenizer = new StringTokenizer(patterns, ",");
/* 214 */       List<String> basenamesList = new LinkedList();
/* 215 */       basenamePatterns.add(basenamesList);
/* 216 */       while (tokenizer.hasMoreTokens()) {
/* 217 */         String pattern = tokenizer.nextToken().trim();
/* 218 */         basenamesList.add(pattern);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 236 */     int lastSlash = uri.lastIndexOf('/');
/* 237 */     int prevSlash = uri.substring(0, lastSlash).lastIndexOf('/');
/* 238 */     String basedir = uri.substring(prevSlash, lastSlash + 1);
/* 239 */     String dirname = getDirPath("");
/* 240 */     String filenames = uri.substring(uri.lastIndexOf('/') + 1);
/* 241 */     String classnames = filenames.substring(0, filenames.indexOf('.'));
/* 242 */     StringTokenizer tokenizer = new StringTokenizer(classnames, ",");
/*     */     
/* 244 */     if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 245 */       for (List<String> basenames : basenamePatterns) {
/* 246 */         ZimbraLog.zimlet.debug("!!! basenames: %s", new Object[] { basenames });
/*     */       }
/* 248 */       ZimbraLog.zimlet.debug("!!! basedir: %s", new Object[] { basedir });
/*     */     }
/* 250 */     while (tokenizer.hasMoreTokens()) {
/* 251 */       String classname = tokenizer.nextToken();
/* 252 */       if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 253 */         ZimbraLog.zimlet.debug("!!! classname: %s", new Object[] { classname });
/*     */       }
/* 255 */       load(req, out, locale, basenamePatterns, basedir, dirname, classname);
/*     */     }
/* 257 */     return bos.toByteArray();
/*     */   }
/*     */   
/*     */   protected void load(HttpServletRequest req, DataOutputStream out, Locale locale, List<List<String>> basenamePatterns, String basedir, String dirname, String classname)
/*     */     throws IOException
/*     */   {
/* 263 */     String basename = basedir + classname;
/*     */     
/* 265 */     out.writeBytes("// Basename: " + Props2Js.getCommentSafeString(basename) + '\n');
/* 266 */     for (List<String> basenames : basenamePatterns) {
/*     */       try {
/* 268 */         ClassLoader parentLoader = getClass().getClassLoader();
/* 269 */         PropsLoader loader = new PropsLoader(parentLoader, basenames, basedir, dirname, classname);
/*     */         
/*     */ 
/*     */ 
/* 273 */         ResourceBundle.getBundle(basename, locale, loader, new ResourceBundle.Control()
/*     */         {
/*     */ 
/*     */           public List<Locale> getCandidateLocales(String baseName, Locale locale)
/*     */           {
/* 278 */             if (baseName == null) {
/* 279 */               throw new NullPointerException();
/*     */             }
/* 281 */             if ((locale.equals(new Locale("zh", "HK"))) || (locale.equals(new Locale("zh", "CN"))) || (locale.equals(new Locale("zh", "TW"))))
/*     */             {
/* 283 */               return Arrays.asList(new Locale[] { locale, Locale.ROOT });
/*     */             }
/*     */             
/*     */ 
/* 287 */             return super.getCandidateLocales(baseName, locale);
/*     */           }
/*     */         });
/* 290 */         for (File file : loader.getFiles()) {
/* 291 */           Props2Js.convert(out, file, classname);
/*     */         }
/*     */       } catch (MissingResourceException e) {
/* 294 */         out.writeBytes("// properties for " + classname + " not found\n");
/*     */       } catch (IOException e) {
/* 296 */         out.writeBytes("// properties error for " + classname + " - see server log\n");
/*     */         
/* 298 */         ZimbraLog.zimlet.error(e.getMessage());
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public static class PropsLoader extends ClassLoader
/*     */   {
/*     */     private List<File> files;
/*     */     private List<String> patterns;
/*     */     private String dir;
/*     */     private String dirname;
/*     */     private String name;
/* 310 */     private static Pattern RE_LOCALE = Pattern.compile(".*(_[a-z]{2}(_[A-Z]{2})?)\\.properties");
/* 311 */     private static Pattern RE_SYSPROP = Pattern.compile("\\$\\{(.*?)\\}");
/*     */     
/*     */     public PropsLoader(ClassLoader parent, List<String> patterns, String basedir, String dirname, String classname)
/*     */     {
/* 315 */       super();
/* 316 */       this.patterns = patterns;
/* 317 */       this.dir = basedir.replaceAll("/[^/]+$", "").replaceAll("^.*/", "");
/* 318 */       this.dirname = dirname;
/* 319 */       this.name = classname;
/* 320 */       this.files = new LinkedList();
/*     */     }
/*     */     
/*     */     public List<File> getFiles() {
/* 324 */       return this.files;
/*     */     }
/*     */     
/*     */     public InputStream getResourceAsStream(String rname)
/*     */     {
/* 329 */       String filename = rname.replaceAll("^.*/", "");
/* 330 */       Matcher matcher = RE_LOCALE.matcher(filename);
/* 331 */       String locale = matcher.matches() ? matcher.group(1) : "";
/* 332 */       String ext = rname.replaceAll("^[^\\.]*", "");
/* 333 */       for (String basename : this.patterns) {
/* 334 */         basename = basename.replaceAll("\\$\\{dir\\}", this.dir);
/* 335 */         basename = basename.replaceAll("\\$\\{name\\}", this.name);
/* 336 */         basename = replaceSystemProps(basename);
/* 337 */         basename = basename + locale + ext;
/* 338 */         File file = new File(this.dirname + basename);
/* 339 */         if (!file.exists()) {
/* 340 */           file = new File(basename);
/*     */         }
/* 342 */         if (file.exists()) {
/* 343 */           this.files.add(file);
/* 344 */           return new ByteArrayInputStream(new byte[0]);
/*     */         }
/*     */       }
/* 347 */       return super.getResourceAsStream(rname);
/*     */     }
/*     */     
/*     */     private static String replaceSystemProps(String s) {
/* 351 */       Matcher matcher = RE_SYSPROP.matcher(s);
/* 352 */       if (!matcher.find()) {
/* 353 */         return s;
/*     */       }
/* 355 */       StringBuilder str = new StringBuilder();
/* 356 */       int index = 0;
/*     */       do {
/* 358 */         str.append(s.substring(index, matcher.start()));
/* 359 */         String pname = matcher.group(1);
/* 360 */         String pvalue = System.getProperty(pname);
/* 361 */         str.append(pvalue != null ? pvalue : matcher.group(0));
/* 362 */         index = matcher.end();
/* 363 */       } while (matcher.find());
/* 364 */       str.append(s.substring(index));
/* 365 */       return str.toString();
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/zimlet/ZimletProps2JsServlet.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */